package com.gxitsky.plugin.classloader;

import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * @author gxing
 * @desc TODO
 * @date 2021/12/31
 */
public class JarURLClassLoader {
    private URL url;
    private URLClassLoader classLoader;

    public JarURLClassLoader(URL url) {
        this.url = url;
        classLoader = new URLClassLoader(new URL[]{url});
    }

    public Set<Class> loadClass(Class<?> superClass, String basePackage) throws IOException, ClassNotFoundException {
        JarFile jarFile = ((JarURLConnection) url.openConnection()).getJarFile();
        Set<Class> classSet = new HashSet<>();
        String packagePath = basePackage.replace(".", "/");
        Enumeration<JarEntry> entries = jarFile.entries();
        while (entries.hasMoreElements()) {
            JarEntry jarEntry = entries.nextElement();
            String entryName = jarEntry.getName();
            if (jarEntry.isDirectory() || !entryName.startsWith(packagePath) || !entryName.endsWith(".class")) {
                continue;
            }
            String classPath = entryName.substring(0, entryName.length() - 6);
            String className = classPath.replace("/", ".");
            Class<?> aClass = classLoader.loadClass(className);
            boolean anInterface = aClass.isInterface();
            boolean assignableFrom = superClass.isAssignableFrom(aClass);
            if (!anInterface && assignableFrom) {
                classSet.add(aClass);
            }
        }
        return classSet;

//        URL url = new URL("file:///D:/service-impl-1.0.0-SNAPSHOT.jar");
//        URLClassLoader loader = new URLClassLoader(new URL[]{url});
//        Class<?> aClass = loader.loadClass("com.gxitsky.plugin.Base64Encode");
//        boolean assignableFrom2 = IFunction.class.isAssignableFrom(aClass);
//        System.out.println(assignableFrom2);
    }

    /**
     * 在指定包路径下加载子类
     *
     * @param superClass
     * @param basePackage
     * @return
     */
//    public Set<Class> loadClass(Class<?> superClass, String basePackage) {
//        JarFile jarFile;
//        try {
//            jarFile = ((JarURLConnection) jar.openConnection()).getJarFile();
//        } catch (Exception e) {
//            e.printStackTrace();
//            return null;
//        }
//        return loadClassFromJar(superClass, basePackage, jarFile);
//    }

//    private Set<Class> loadClassFromJar(Class<?> superClass, String basePackage, JarFile jar) {
//        Set<Class> classes = new HashSet<>();
//        String pkgPath = basePackage.replace(".", "/");
//        Enumeration<JarEntry> entries = jar.entries();
//        Class<?> clazz;
//        while (entries.hasMoreElements()) {
//            JarEntry jarEntry = entries.nextElement();
//            String entryName = jarEntry.getName();
//            if (entryName.charAt(0) == '/') {
//                entryName = entryName.substring(1);
//            }
//            if (jarEntry.isDirectory() || !entryName.startsWith(pkgPath) || !entryName.endsWith(".class")) {
//                continue;
//            }
//            String className = entryName.substring(0, entryName.length() - 6);
////            className = className.replace("/", ".");
////            className = "com.gxitsky.plugin.Base64Encode";
//            clazz = loadClass(className.replace("/", "."));
//            boolean assignableFrom1 = superClass.isAssignableFrom(clazz);
//            Class<IFunction> iFunctionClass = IFunction.class;
//            boolean assignableFrom2 = iFunctionClass.isAssignableFrom(clazz);
//            System.out.println(assignableFrom2);
//            if (!clazz.isInterface() && assignableFrom1) {
//                classes.add(clazz);
//            }
//        }
//        return classes;
//    }

//    private Class<?> loadClass(String name) {
//        try {
//            return classLoader.loadClass(name);
//        } catch (ClassNotFoundException e) {
//            e.printStackTrace();
//        }
//        return null;
//    }

}
